package com.maas.util.mybatis.jpa.littlenb.conditions.plus.core.toolkit.util;


import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 字段处理器
 * @author viaco
 */
public class FieldUtil {

    /**
     * 递归Model的父类去getDeclaredFields()
     * @param tempClass
     * @return
     */
    public static  Field[]  getDeclaredFields(Class tempClass) {

        List<Field> fieldList = new ArrayList<>() ;
        Field[] fieldLi = null ;
        String objectClass = "java.lang.object";
        while (tempClass != null && !objectClass.equals(tempClass.getName().toLowerCase())) {
            //当父类为null的时候说明到达了最上层的父类(Object类).
            fieldList.addAll(Arrays.asList(tempClass .getDeclaredFields()));
            //得到父类,然后赋给自己
            tempClass = tempClass.getSuperclass();
        }
        fieldLi = new Field[fieldList.size()];

        for (int i = 0; i <fieldList.size() ; i++) {
            fieldLi[i] = fieldList.get(i);
        }
        return fieldLi;
    }

    public static Field  getField(Class tempClass,String fileName){
        Field[]  getDeclaredFields = getDeclaredFields(tempClass);
        for (Field field : getDeclaredFields){
            String currFieldName = field.getName();
            if(currFieldName.equals(fileName)){
                return field;
            }
        }
        return null;
    }


    public static <T>void fatherToChild(T father,T child) throws Exception {
        if (child.getClass().getSuperclass()!=father.getClass()){
            throw new Exception("child 不是 father 的子类");
        }
        Class<?> fatherClass = father.getClass();
        Class<?> childClass = child.getClass();

        Field[] declaredFields = getDeclaredFields(fatherClass);

        Method[] m = childClass.getMethods();
        for (int i = 0; i < declaredFields.length; i++) {
            Field field=declaredFields[i];
            String fieldName = field.getName();
            String methodName = "get"+upperHeadChar(field.getName());
            //Method method=fatherClass.getDeclaredMethod(methodName)
            Method method=fatherClass.getMethod(methodName);
            Object obj = method.invoke(father);
            //field.setAccessible(true)
            //field.set(child,obj)

            try {
                Class<?> typeClass = getField(childClass,fieldName).getType();
                setValue(child, childClass,fieldName, typeClass, obj);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }



    /**
     * 根据属性，拿到set方法，并把值set到对象中
     * @param obj 对象
     * @param clazz 对象的class
     * @param fileName 需要设置值得属性
     * @param typeClass
     * @param value
     */
    public static void setValue(Object obj,Class<?> clazz,String filedName,Class<?> typeClass,Object value) {
        filedName = removeLine(filedName);
        String methodName = "set" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
        try {
            //Method method = clazz.getDeclaredMethod(methodName, new Class[]{typeClass})
            Method method = clazz.getMethod(methodName, new Class[]{typeClass});
            method.invoke(obj, new Object[]{getClassTypeValue(typeClass, value)});
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

        /**
         * 首字母大写，in:deleteDate，out:DeleteDate
         */
    public static String upperHeadChar(String in) {
        String head = in.substring(0, 1);
        String out = head.toUpperCase() + in.substring(1, in.length());
        return out;
    }


    /**
     * 通过class类型获取获取对应类型的值
     * @param typeClass class类型
     * @param value 值
     * @return Object
     */
    private static Object getClassTypeValue(Class<?> typeClass, Object value){
        if(typeClass == int.class  || value instanceof Integer){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == short.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == byte.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == double.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == long.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == String.class){
            if(null == value){
                return "";
            }
            return value;
        }else if(typeClass == boolean.class){
            if(null == value){
                return true;
            }
            return value;
        }else if(typeClass == BigDecimal.class){
            if(null == value){
                return new BigDecimal(0);
            }
            return new BigDecimal(value+"");
        }else {
            return typeClass.cast(value);
        }
    }
    /**
     * 处理字符串  如：  abc_dex ---> abcDex
     * @param str
     * @return
     */
    public static  String removeLine(String str){
        if(null != str && str.contains("_")){
            int i = str.indexOf("_");
            char ch = str.charAt(i+1);
            char newCh = (ch+"").substring(0, 1).toUpperCase().toCharArray()[0];
            String newStr = str.replace(str.charAt(i+1), newCh);
            String newStr2 = newStr.replace("_", "");
            return newStr2;
        }
        return str;
    }

    /**
     * 获取字段值
     * @param o
     * @param fieldName
     * @return
     */
    public static Object getFieldValueByName(Object o, String fieldName) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[] {});
            Object value = method.invoke(o, new Object[] {});
            return value;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
    }

    /**
     * 设置字段值
     * @param obj
     * @param fieldName
     * @param value
     */
    public static void setFieldValueByName(Object obj, String fieldName, Object value){
        try {
            // 获取obj类的字节文件对象
            Class c = obj.getClass();
            // 获取该类的成员变量
            Field f = c.getDeclaredField(fieldName);
            // 取消语言访问检查
            f.setAccessible(true);
            // 给变量赋值
            f.set(obj, value);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }
}
